import 'dart:convert';

import 'package:color_dart/color_dart.dart';
import 'package:flutter/material.dart';
import 'package:flutter_luckin_coffee/components/abutton/index.dart';
import 'package:flutter_luckin_coffee/components/astepper/AStepper.dart';
import 'package:flutter_luckin_coffee/jsonserialize/goods_detail/data.dart';
import 'package:flutter_luckin_coffee/jsonserialize/goods_price/data.dart';
import 'package:flutter_luckin_coffee/jsonserialize/shopping_cart/data.dart';
import 'package:flutter_luckin_coffee/provider/shopping_cart_model.dart';
import 'package:flutter_luckin_coffee/utils/global.dart';
import 'package:flutter_luckin_coffee/widgets/goods_detail/select_row.dart';
//含状态组件，商品详情，按翻译
class GoodsDetailDialog extends StatefulWidget {
  //设置id
  final int id;
  //获取购物车观察model，能够实现状态变更通知
  final ShoppingCartModel model;
//构造函数，包括 key  id   model对象
  GoodsDetailDialog({
    Key key,
    this.id,
    this.model
  }) : super(key: key);
//创建状态组件，
  _GoodsDetailDialogState createState() => _GoodsDetailDialogState();
}
//获取状态组件，继承自状态
class _GoodsDetailDialogState extends State<GoodsDetailDialog> {
  /// 当前选中规格信息   当前选中的规格map
  Map defaultValue = {
    "spec": {
      // typeId: childId,
      // typeId: childId,
    },
    "specName": "",
    "price": 0,
    "num": 1,
  };
//保存的 购物车model
  ShoppingCartModel _shoppingCartModel;
//商品详情的保存数据
  GoodsDetailData data;
//状态组件的初始化状态方法
  @override
  void initState() {
    super.initState();
//获取 观察状态的购物车数据model
    _shoppingCartModel = widget.model;
    //异步实现future   延迟0，实现以下方法
    Future.delayed(Duration.zero, () async{
      //通过dio包，实现get请求/shop/goods/detail  传入参数是，商品id，获取结果集map
      Map result = await G.dio.get('/shop/goods/detail', queryParameters: {
        "id": widget.id
      });

      //商品详情数据， 将键值集合解析成数据类
      GoodsDetailData goodsDetailData = GoodsDetailData.fromJson(result['data']);

      // 格式化默认规格   增加 键类型为string  值类型为int的 键值对集合
      Map<String, int> spec = {};
      //非空方式获取 defaultSpec
      String defaultSpec = goodsDetailData.extJson?.defaultSpec;
      //字符串为空时，
      if(goodsDetailData.extJson.defaultSpec == null) {
        //遍历属性集合List，赋予 id为键，属性id为值，填充map的spec集合
        goodsDetailData.properties.forEach((val) {
          spec['${val.id}'] = val.childsCurGoods[0].id;
        }); 
      } else {
        //不为空，则替换所有 \' 为 \"  并通过json转化，将字符串转化为 map集合
        Map<String, dynamic> specDecode = json.decode(defaultSpec.replaceAll('\'', "\""));
        //规格map遍历， 获取key和value，将key和值赋予规格集合
        specDecode.forEach((key, value) {
          //字符串转int  int.parse(value.toString());  parse即可
          spec['$key'] = int.parse(value.toString());
        });
      }

      // 获取当前规格的价格  异步获取价格， 传入 规格map  数据传入商品详情
      //await 关键字， 代表此代码要异步执行了
      Map resultPrice = await _getGoodsPrice(spec, data: goodsDetailData);

      //获取结果集的状态  status
      if(resultPrice['status']) {
        //解析data数据为 商品价格数据
        GoodsPrice goodsPrice = GoodsPrice.fromJson(resultPrice['data']);
        //数据的data类型为价格数据
        GoodsPriceData goodsPriceData = goodsPrice.data;

        //设置状态， 保存数据，规格，价格，规格名称
        setState(() {
          data = goodsDetailData;
          defaultValue['spec'] = spec;
          defaultValue['price'] = goodsPriceData.price;
          defaultValue['specName'] = goodsPriceData.propertyChildNames;
        });
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    //在给定的时间内，自动完成转换缩进到给定的padding值
    //通过设置curve 来指定动画的运行速率动画
    return AnimatedPadding(
      //内边距设置为 0
      padding: EdgeInsets.zero,
      //设置不可变持续时间为  100 ms
      duration: const Duration(milliseconds: 100),
      //当前变化状态为， Curves.decelerate  先快后慢
      curve: Curves.decelerate,
      //设置动画子组件  MediaQuery是建立媒体查询解析给定数据的子树。

//      MediaQuery  常用的是获取屏幕高度属性  插入要移除的视图
    //todo 怎么理解得再解释
      child: MediaQuery.removeViewInsets(
        //todo 怎么理解得再解释
        removeLeft: true,
        removeTop: true,
        removeRight: true,
        removeBottom: true,
        //上下文参数
        context: context,
        //增加子组件，center  居中组件
        child: Center(
          //子组件，约束组件， minWidth 满足约束条件的最小宽度
          //            maxWidth 满足约束条件的最大宽度；可能是[double.infinity]（1.0 / 0.0）
          //            minHeight 满足约束条件的最小高度
          //            maxHeight 满足约束条件的最大高度；可能是[double.infinity]（1.0 / 0.0）
          //以上这些属性
          child: ConstrainedBox(
            //约束组件的约束对象，BoxConstraints   设置约束属性为 最小宽度为280
            constraints: const BoxConstraints(minWidth: 280.0),
            //子组件，设计 md风格的样式，包括 阴影高度，圆角，阴影颜色，方式等
            child: Material(
              //透明颜色
              color: Colors.transparent,
              //阴影24度
              elevation: 24.0,
              //裁剪边缘，  圆角 4度
              shape:  RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0))),
              //样式为纸片样式
              type: MaterialType.card,
              //加入子组件
              child: _initContent(),
            ),
          ),
        ),
      ),
    );
  }

    /// 获取当前规定价格  获取当前价格并返回一个map集合
  /// //传参包括，规格集合，商品数据
  Future<Map> _getGoodsPrice(Map<String, int> spec, {
    @required GoodsDetailData data
  }) async {
    //一个键值对集合，字符串为键，dynamic 任意类型为值类型
    Map<String, dynamic> resultJson = {};

    /// status为false没有获取到规格 || 规格没有任何修改不发起请求
    if(defaultValue['spec'].toString() == spec.toString()) return {
      "status": false,
      "data": null
    };

    //吊起进度条，进行显示
    G.loading.show(context);
//格式化 规格字符串，并转化为字符串  替换\\s|{|}为空格
    String propertyChildIds = spec.toString().replaceAll(RegExp('\\s|{|}'), '');
    // print(propertyChildIds);
    try {
      //调取 请求价格的接口， 增加参数 goodsId    propertyChildIds  传入id和规格，虽然不知道是怎么定义的商品详情参数
      Map result = await G.dio.post('/shop/goods/price', queryParameters: {
        "goodsId": data.basicInfo.id,
        "propertyChildIds": propertyChildIds
      });
      //定义结果，请求成功，true
      resultJson['status'] = true;
      resultJson['data'] = result;
    } catch(e) {
      //定义结果，请求失败，false
      resultJson['status'] = false;
      resultJson['data'] = e;
    }

    //取消进度条
    G.loading.hide(context);
    //返回结果集
    return resultJson;
  }

  //初始化框架内容
  _initContent() {
    //无数据时，
    if(data == null) {
      //显示一个 容器  宽度 335  高度 580 边框，圆角为8 白色的
      return Container(
        width: 335,
        height: 580,
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(8),
          color: hex('#fff'),
        ),
        //子组件  Stack 叠加组件，类似framelayout的组合方式
        child: Stack(
          //子组件组合
          children: <Widget>[
            //子组件集合
            _initClose()
          ],
        )
      );
    }
    //返回一个盒子控件，宽度 335   高度 580
    return Container(
      width: 335,
      height: 580,
      //竖向排列的 组件集合，
      child: Column(
        children: <Widget>[
          //头部组件
          _initHeader(),
          //展开组件
          //Expanded组件可以使Row、Column、Flex等子组件在其主轴方向上展开并填充可用空间
          //充满内部内容
          Expanded(
            child: Container(
              //盒子颜色
              color: hex('#fff'),
              //竖直方向 12个距离
              padding: EdgeInsets.symmetric(vertical: 12),
              //单个子组件的容器组件，滑动
              child: SingleChildScrollView(
                //竖直方向，cloumn 组件，支持多个组件放到内部
                child: Column(
                  //
                  children: <Widget>[
                    _initOption(),
                    _line(),
                    _initGoodsDesc()
                  ],
                )
              ),
            ),
          ),
        
          _initAccount(),
          _initFooter()
        ],
      ),
    );
  }

  /// 分隔线
  _line() {
    //分割线组件
    return Container(
      //内边距  顶部导航栏和两侧的距离，水平15  竖直8
      padding: EdgeInsets.symmetric(horizontal: 15, vertical: 8),
      //子组件，组件框架，
      child: Container(
        //边框样式，边框样式底部边框
        decoration: BoxDecoration(
          border: G.borderBottom()
        ),
      ),
    );
  }

  /// 选项
  _initOption() {
    //组件数组
    List<Widget> widgets = [];
    //遍历属性，
    data.properties.forEach((GoodsDetailProperty item) {
      //增加组件数据
      widgets.add(
        //自己创建的一个组件，SelectRow  无状态
        SelectRow(
          //设置id为 规格的id
          id: defaultValue['spec']['${item.id}'],
          // 传入 商品数据
          data: item,
          //改变方法，传入方法对象
          onChange: (Map type) async{
            //async  异步操作
            //将规格数据转化为map数据
            Map<String, int> spec = Map.from(defaultValue['spec']);
            //type和规格取值
            spec['${type['typeId']}'] = type['childId'];

            // 异步执行方法 _getGoodsPrice  私有的  传入规格map   商品数据，生成集合map
            Map result = await _getGoodsPrice(spec, data: data);
            //获取状态  请求结果  true 表示请求成功
            if(result['status']) {
              //把数据解析成 商品价格
              GoodsPrice goodsPrice = GoodsPrice.fromJson(result['data']);
              //价格数据 data 获取
              GoodsPriceData goodsPriceData = goodsPrice.data;

              //保存到状态中  规格map  价格对象price  规格名称 specName
              setState(() {
                defaultValue['spec'] = spec;
                defaultValue['price'] = goodsPriceData.price;
                defaultValue['specName'] = goodsPriceData.propertyChildNames;
              });
            }
          },
        )
      );
    });
    //竖直多格子  多个子组件 水平分布
    return Column(
      //组件集合
      children: <Widget>[
        //盒子容器，单纯包裹一下  目前看来，这层包裹是可以不要的
        Container(child:
            //竖直容器，  传入刚刚组装的规格组件
          Column(children: widgets,),
        ),
      ],
    );
  }

  /// 商品描述
  Widget _initGoodsDesc() {
    //替换所有字符串中的 <.*?p> 字符  \\\\n  转为\n
    String desc = data.content.replaceAll(RegExp("<.*?p>"), "").replaceAll(RegExp('\\\\n'), '\n');

    //盒子组件，
    return Container(
      //组件间距，水平15  竖直8  做的内边距
      padding: EdgeInsets.symmetric(horizontal: 15, vertical: 8),
      // 竖直组件 column
      child: Column(
        //配置排列位置在起始位置
        mainAxisAlignment: MainAxisAlignment.start,
        //增加 子组件 widget
        children: <Widget>[
          //水平放行，子组件数组，
          Row(children: <Widget>[
            //展开组件，设置内部组件的展开范围，  这里也是多余的包裹，目前理解没有实际作用
            Expanded(child:
                //文本组件，描述   文本样式，文字是 颜色，，，文字大小是13
              Text('商品描述',style: TextStyle(color: rgba(56, 56, 56, 1),fontSize: 13),),
            )
          ],),
          //水平方向 组件，排列所有的子组件为平方
          Row(children: <Widget>[
            //展开组件排列样式， 默认的排列样式是
            Expanded(child:
                //盒子容器，设置了 高度外边距为8，文本组件作为内部组件，文字大小为12，颜色灰色
              Container(
                margin: EdgeInsets.only(top: 8),
                child: Text(desc,
                  style: TextStyle(
                    fontSize: 12,
                    color: rgba(128, 128, 128, 1)
                  ),
                )
              )
            ,)
          ],)
      ],),
    );
  }

  /// 结算总价
  Widget _initAccount() {
    //计算价格显示，  盒子组件，
    return Container(
      //内部左上右  15  15  10
      padding: EdgeInsets.only(left: 15, right: 15, top: 10),
      //外部边距，
      decoration: BoxDecoration(
        //顶部边距为 顶部边线 颜色 宽度为1
        border: Border(
          top: BorderSide(color: rgba(242, 242, 242, 1), width: 1),
          //底部边距为 顶部边线 颜色 宽度为1
          bottom:  BorderSide(color: rgba(242, 242, 242, 1), width: 1),
        ),
        //颜色 白色
        color: hex('#fff'),
      ),
      //高度60
      height: 60,
      //竖直组件，子组件列表
      child: Column(children: <Widget>[
        //水平组件，子组件列表
        Row(
          //按照空列表走，
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          //子数组列表
          children: <Widget>[
            //容器盒子，
            Container(
              //依据左边居中派排列
              alignment: Alignment.centerLeft,
              //文本 $ 价格和数量  文字大小 18   加粗   颜色 56 56
              child: Text('￥${defaultValue["price"]*defaultValue["num"]}', style: TextStyle(
                fontSize: 18,
                fontWeight: FontWeight.bold,
                color: rgba(56, 56, 56, 1)),
              ),
            ),
            //计步组件
            AStepper(
              //数量，表示的是步数
              value: defaultValue['num'],
              //最小值1
              min: 1,
              //改变时操作
              onChange: (num val) {
                //将数量保存到num中
                setState(() {
                  defaultValue['num'] = val;
                });
              },
            )
        ],),
        //容器盒子
        Container(
          //左边居中水平显示
          alignment: Alignment.centerLeft,
          //子组件为增加的文本组件，同时操作文本内容替换所有的特殊字符
          child: 
            Text('${data.basicInfo.name} ${defaultValue['specName'].replaceAll(RegExp(',\$'), '').replaceAll(RegExp(G.regExpRules['specName']), '')}',
            //文本的颜色，字体大小
              style: TextStyle(
              color: rgba(80, 80, 80, 1),
              fontSize: 10
            ),
          )
        )
      ],),
    ); 
  }

  /// 底部
  Widget _initFooter() {
    //底部内容    容器盒子
    return Container(
      //内部边距 左右 15 15
      padding: EdgeInsets.only(left: 15, right: 15),
      //设置边距内容，  左角 8 弧度   右角  8 弧度  颜色白色  十六禁止的颜色显示   hex('#fff'),
      decoration: BoxDecoration(
        borderRadius: BorderRadius.only(bottomLeft: Radius.circular(8), bottomRight: Radius.circular(8)),
        color: hex('#fff'),
      ),
      //高度 60 的盒子
      height: 60,
      //子组件 水平组件
      child: Row(
        //组件按照，中间空，两边填满的方式排列
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        //子组件列表
        children: <Widget>[
          //自定义按钮组件，图标 icon
          AButton.icon(
            //自定义的图标组件  尺寸在14大小
            icon: icontupian17(size: 14,),
            //子组件为 文本组件， 文本大小为12
            textChild: Text('充2赠1', style: TextStyle(fontSize: 12),),
            //文本为白色
            color: hex('#fff'),
            //颜色
            bgColor: rgba(255, 129, 2, 1),
            //高度为 32
            height: 32,
            //按键效果，空，但是有点击
            onPressed: () => {}
          ),
          //按钮图标
          AButton.icon(
            //高度为32
            height: 32,
            //图标大小为14
            icon: iconsc(size: 14,),
            //子组件为文本组件， 文字，文本大小为12
            textChild: Text('收藏口味', style: TextStyle(fontSize: 12),),
            //文字颜色
            color: rgba(136, 175, 213, 1),
            //背景颜色
            bgColor: rgba(136, 175, 213, 0.3),
            //点击效果，
            onPressed: () => {}
          ),
          //按钮图标
          AButton.icon(
            //高度为32
            height: 32,
            //定义图标大小为14
            icon: icongouwuche(size: 14,),
            bgColor: rgba(136, 175, 213, 1),
            color: hex('#fff'),
            textChild: Text('加入购物车', style: TextStyle(fontSize: 12),),
            //点击事件，有异步内容
            onPressed: () async {
              //展开进度条
              G.loading.show(context);
              //实现异步的休眠，有个delay方法
              await G.sleep();

              //如果成功
              if(mounted) {
                //保存了包括，id  name  等内容的map    dynamic  任意类型
                Map<String, dynamic> mockdata = {
                  "id": data.basicInfo.id,
                  "name": data.basicInfo.name,
                  "price": defaultValue['price'],
                  "number": defaultValue['num'],
                  "spec": defaultValue['spec'],
                  "specName": defaultValue['specName'],
                };
                ShoppingCartData shoppingCartData = ShoppingCartData.fromJson(mockdata);

                _shoppingCartModel.add(shoppingCartData);
              }
              
              G.loading.hide(context);
              //返回页面，pop出页面
              G.pop();

              //展开toast  临时弹窗信息
              G.toast.show(context, '加入购物车成功');
            }
          )
        ],
      ),
    );
  }

  /// 收藏
  Widget _circelIcon({Icon icon, Function onPress, Color bgColor}) {
    //收藏按钮  水波纹效果   内部组件不能时wihte背景色
    return InkWell(
      // 盒子组件
      child: Container(
        //全部内边距为5
        padding: EdgeInsets.all(5),
        //居中显示
        alignment: Alignment.center,
        //边框，背景色，圆角为20
        decoration: BoxDecoration(
          color: bgColor == null ? rgba(0, 0, 0, 0.3) : bgColor,
          borderRadius: BorderRadius.all(Radius.circular(20))
        ),
        child: icon
      ),
      //单机效果
      onTap: () {
        //点击效果，查看点击方法
        if(onPress!=null) {
          onPress();
        }
      },
    );
  }

  /// 关闭弹窗
  Widget _initClose() {
    // 关闭  关闭   定位组件position  right 10  top10
    return Positioned(
      right: 10,
      top: 10,
      //增加水波纹效果
      child: InkWell(
        //盒子组件，
        child: Container(
          //内边距为5
          padding: EdgeInsets.all(5),
          //居中显示
          alignment: Alignment.center,
          //边框  背景色 000  角度为圆角 20
          decoration: BoxDecoration(
            color: rgba(0, 0, 0, 0.3),
            borderRadius: BorderRadius.all(Radius.circular(20))
          ),
          //图标背景组件  白背景  16大小
           child: iconhebingxingzhuang(color: hex('#fff'), size: 16),
        ),
        //点击效果
        onTap: () {
          //退出当前页面
          Navigator.pop(context);
        },
      )
    );
  }

  /// 头部
  Widget _initHeader() {
    //顶部组件  类似frame的堆叠组件
    return Stack(children: <Widget>[
      //盒子组件，宽度 335  高度 150
      Container(
        width: 335,
        height: 150,
        //裁剪组件  底部有 8角度的圆角    拉取本地图片文件 jpg  Image.asset  填充方式 BoxFit
        child: ClipRRect(
          borderRadius: BorderRadius.only(topLeft: Radius.circular(8), topRight: Radius.circular(8)),
          child: Image.asset('lib/assets/images/menu/dialog1.jpg', height: 150, fit: BoxFit.cover,),
        ),
      ),

      //关闭方式
      _initClose(),

      // 收藏
      Positioned(
        //位置 左边距10  右边距10
        left: 10,
        top: 10,
        //子组件图标，  尺寸16
        child: _circelIcon(
          icon: iconsc(color: hex('#fff'), size: 16),
        )
      ),

      // 标题
      Positioned(
        //左右 各15 边距  竖直组件，
        left: 15,
        bottom: 15,
        //竖直组件内部包括，两个问问  白色 22大小的名字，白色14大小的分类
        child: Column(children: <Widget>[
          Text(data.basicInfo.name, 
            style: TextStyle(fontSize: 22,fontWeight: FontWeight.bold, color: hex('#fff')),
          ),
          Text(data.basicInfo.characteristic, 
            style: TextStyle(fontSize: 14,color: hex('#fff')),
          )
        ],),
      )
    ],);
  }
}

  